package net.guerlab.smart.uploader.service.controller;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.guerlab.smart.uploader.service.exception.FilePathLevelOverflowException;
import net.guerlab.smart.uploader.service.exception.NotFindFileException;
import net.guerlab.smart.uploader.service.properties.UploadProperties;
import net.guerlab.spring.upload.entity.IFileInfo;
import net.guerlab.spring.upload.generator.DateSavePathGenerator;
import net.guerlab.spring.upload.generator.RandomSaveNameGenerator;
import net.guerlab.spring.upload.helper.UploadFileHelper;
import net.guerlab.spring.upload.utils.FileBase64Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 抽象上传处理控制器
 *
 * @author guer
 */
public abstract class AbstractUploadController {

    protected static final String DEFAULT_PATH = "/";

    protected UploadProperties uploadProperties;

    /**
     * 获取基准路径
     *
     * @return 基准路径
     */
    protected abstract String getBasePath();

    @ApiOperation("上传文件")
    @PostMapping({ "/single", "/single/**" })
    public IFileInfo single(@ApiParam(value = "待上传文件") @RequestParam(required = false) MultipartFile file,
            @ApiParam(value = "待上传文件base64") @RequestParam(required = false) String fileBase64,
            HttpServletRequest request) {
        if (file == null && fileBase64 != null) {
            file = FileBase64Utils.parse(fileBase64);
        }

        if (file == null) {
            throw new NotFindFileException();
        }

        return UploadFileHelper
                .upload(file, dateSavePathGenerator(request, "single"), RandomSaveNameGenerator.INSTANCE);
    }

    @ApiOperation("多文件列表上传")
    @PostMapping({ "/multiple", "/multiple/**" })
    public List<IFileInfo> multiple(
            @ApiParam(value = "待上传文件") @RequestParam(required = false) List<MultipartFile> fileList,
            @ApiParam(value = "待上传文件base64") @RequestParam(required = false) List<String> fileBase64List,
            HttpServletRequest request) {
        if (fileList == null || fileList.isEmpty()) {
            if (fileBase64List != null && !fileBase64List.isEmpty()) {
                fileList = fileBase64List.stream().map(FileBase64Utils::parse).filter(Objects::nonNull)
                        .collect(Collectors.toList());
            }
        }

        if (fileList == null || fileList.isEmpty()) {
            throw new NotFindFileException();
        }

        return UploadFileHelper
                .multiUpload(fileList, dateSavePathGenerator(request, "multiple"), RandomSaveNameGenerator.INSTANCE);
    }

    private DateSavePathGenerator dateSavePathGenerator(HttpServletRequest request, String type) {
        String basePath = getBasePath();
        String base = basePath.endsWith(DEFAULT_PATH) ? basePath + type : basePath + DEFAULT_PATH + type;
        String servletPath = request.getServletPath();
        String path = servletPath.startsWith(base) ? servletPath.substring(base.length()) : "";
        if (path.startsWith(DEFAULT_PATH)) {
            path = path.substring(DEFAULT_PATH.length());
        }

        int maxLength = uploadProperties == null ? UploadProperties.DEFAULT_LEVEL : uploadProperties.getMaxLevel();
        int currentLevel = path.split(DEFAULT_PATH).length;
        if (maxLength > 0 && path.split(DEFAULT_PATH).length > maxLength) {
            throw new FilePathLevelOverflowException(currentLevel, maxLength);
        }

        return new DateSavePathGenerator(path);
    }

    @Autowired
    public void setUploadProperties(UploadProperties uploadProperties) {
        this.uploadProperties = uploadProperties;
    }

}
